package com.rgs.base.core.util;

import cn.hutool.core.util.NumberUtil;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.rgs.base.core.statics.OtherStaticClass;

import java.text.DecimalFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Ren Gaoshuai
 * @ClassName DateFormat
 * @date 2022-03-08 16:18
 **/
public class DateFormat {

    private DateFormat() {
    }


    public static final String DATE_FORMAT_STR = "yyyy-MM-dd";
    public static final String DATE_FORMAT_STR_SIMPLE = "yyyyMMdd";
    public static final DateTimeFormatter DATE_FORMAT
            = DateTimeFormatter.ofPattern(DATE_FORMAT_STR);

    public static final String ES_DATE_FORMAT_STR = "yyyy.MM.dd";
    public static final DateTimeFormatter ES_DATE_FORMAT
            = DateTimeFormatter.ofPattern(ES_DATE_FORMAT_STR);

    public static final String DATETIME_FORMAT_STR = "yyyy-MM-dd HH:mm:ss";
    public static final String DATETIME_FORMAT_STR_SIMPLE = "yyyyMMddHHmmss";
    public static final DateTimeFormatter DATETIME_FORMAT
            = DateTimeFormatter.ofPattern(DATETIME_FORMAT_STR);

    private static final String[] WEEK_ARRAY = {"0", "一", "二", "三", "四", "五", "六", "日"};
    private static final String WEEK_DAY_PREFIX = "星期";

    /**
     * 获取某年的第一天
     *
     * @param year
     * @return java.time.LocalDate
     * @author daxiong
     * @date 2020/5/20 1:43 下午
     */
    public static LocalDate getYearFirst(Integer year) {
        return LocalDate.now().withYear(year).with(TemporalAdjusters.firstDayOfYear());
    }

    /**
     * 获取某年的最后一天
     *
     * @param year
     * @return java.time.LocalDate
     * @author daxiong
     * @date 2020/5/20 1:43 下午
     */
    public static LocalDate getYearLast(Integer year) {
        return LocalDate.now().withYear(year).with(TemporalAdjusters.lastDayOfYear());
    }

    /**
     * 获取某年某个月的第一天
     *
     * @param year
     * @param month
     * @return java.time.LocalDate
     * @author daxiong
     * @date 2020/9/8 5:08 下午
     */
    public static LocalDate getMonthFirst(String year, String month) {
        LocalDate date = LocalDate.parse(year + "-" + month + "-01");
        return date.with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 获取某年某月的最后一天
     *
     * @param year
     * @param month
     * @return java.time.LocalDate
     * @author daxiong
     * @date 2020/9/8 5:08 下午
     */
    public static LocalDate getMonthLast(String year, String month) {
        LocalDate date = LocalDate.parse(year + "-" + month + "-01");
        return date.with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * 根据日期格式获取日期Str
     *
     * @param date
     * @param dateFormatStr
     * @return
     */
    public static String getStringDate(TemporalAccessor date, String dateFormatStr) {
        //yyyy-MM-dd HH:mm:ss
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(dateFormatStr);
        return fmt.format(date);
    }

    public static String getStringDate(LocalDate date) {
        return DATE_FORMAT.format(date);
    }

    public static String getStringDate(LocalDateTime dateTime) {
        return DATETIME_FORMAT.format(dateTime);
    }


    /**
     * 将日期转换为当天的分钟数，取整
     *
     * @param date
     * @return java.lang.Integer
     * @author daxiong
     * @date 2020-04-11 12:16
     */
    public static Integer date2MinuteTotal(LocalDateTime date) {
        int hour = date.getHour();
        int minute = date.getMinute();
        return hour * 60 + minute;
    }


    /**
     * 根据分钟数获取小时
     * eg: 输入570，返回 9.5小时
     *
     * @param minuteTotal
     * @return java.lang.String
     * @author daxiong
     * @date 2020-04-10 13:42
     */
    public static String minute2Hour(Integer minuteTotal) {
        if (minuteTotal == null || minuteTotal < 0) {
            return null;
        }
        Integer modulusMinute = minuteTotal % OtherStaticClass.ONE_DAY_MINUTE;
        float hour = modulusMinute / 60f;
        String format = new DecimalFormat("#.#").format(hour);
        return format + "小时";
    }

    /**
     * 根据分钟数获取小时
     * eg: 输入570，返回 9.5小时
     *
     * @param minuteTotal
     * @return java.lang.String
     * @author daxiong
     * @date 2020-04-10 13:42
     */
    public static String minute2Hour(Double minuteTotal) {
        if (minuteTotal == null || minuteTotal < 0) {
            return null;
        }
        double modulusMinute = minuteTotal % OtherStaticClass.ONE_DAY_MINUTE;
        double hour = modulusMinute / 60;
        String format = new DecimalFormat("#.#").format(hour);
        return format + "小时";
    }

    /**
     * 根据分钟数获取时间
     * eg: 输入540，返回 09:00
     *
     * @param minuteTotal
     * @return java.lang.String
     * @author daxiong
     * @date 2020-04-10 13:42
     */
    public static String minute2HourMinute(Integer minuteTotal) {
        if (minuteTotal == null || minuteTotal < 0) {
            return "";
        }
        Integer modulusMinute = minuteTotal % OtherStaticClass.ONE_DAY_MINUTE;
        int hour = modulusMinute / 60;
        int minute = modulusMinute % 60;
        return Strings.padStart(String.valueOf(hour), 2, '0')
                .concat(":")
                .concat(Strings.padStart(String.valueOf(minute), 2, '0'));
    }


    public static LocalDate parseDate(String dateStr) {
        List<String> strings = Splitter.on('-').omitEmptyStrings().splitToList(dateStr);
        dateStr = strings.stream().map(q -> Strings.padStart(q, 2, '0')).collect(Collectors.joining("-"));
        return LocalDate.parse(dateStr, DATE_FORMAT);
    }

    /**
     * 将日期string转换成日期
     *
     * @param dateStr eg:"20210512"
     * @param format  eg:"yyyyMMdd"
     * @return java.time.LocalDate
     * @author daxiong
     * @date 2021/5/17 上午11:00
     */
    public static LocalDate parseDate(String dateStr, String format) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        return LocalDate.parse(dateStr, formatter);
    }

    /**
     * 判断日期是否在两个目标日期之间
     *
     * @param date
     * @param first
     * @param last
     * @return boolean
     * @author daxiong
     * @date 2020/5/20 1:51 下午
     */
    public static boolean range(LocalDate date, LocalDate first, LocalDate last) {
        return date.isBefore(last) && date.isAfter(first);
    }

    /**
     * 根据指定日期格式将string转成LocalDate
     *
     * @param dateStr
     * @param dateFormat
     * @return
     */
    public static LocalDate stringToLocalDate(String dateStr, String dateFormat) {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(dateFormat);
        return LocalDate.parse(dateStr, fmt);
    }

    /**
     * 根据指定日期格式将string转成localDateTime
     *
     * @param dateStr
     * @param dateFormat
     * @return
     */
    public static LocalDateTime stringToDate(String dateStr, String dateFormat) {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(dateFormat);
        return LocalDateTime.parse(dateStr, fmt);
    }

    /**
     * 获取今天剩余的分钟数
     *
     * @param
     * @return int
     * @author daxiong
     * @date 2020/5/29 9:32 上午
     */
    public static int timeLeftOfDay() {
        Integer timeLeft = date2MinuteTotal(LocalDateTime.now());
        return Math.max(0,
                NumberUtil.sub(OtherStaticClass.ONE_DAY_MINUTE, timeLeft).intValue());
//        return MathUtil.subGreatThenZero(OtherStaticClass.ONE_DAY_MINUTE, timeLeft);
    }

    /**
     * 将Long类型的时间戳转换成String 类型的时间格式，时间格式为：yyyy-MM-dd
     */
    public static String convertTimestampToString(Long time) {
        return ES_DATE_FORMAT.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time),
                ZoneId.systemDefault()));
    }

    /**
     * date转换为LocalDateTime
     *
     * @param time
     * @return java.time.LocalDateTime
     * @author daxiong
     * @date 2020/6/19 11:44 上午
     */
    public static LocalDateTime dateToLocalDateTime(Date time) {
        Instant it = time.toInstant();
        ZoneId zid = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(it, zid);
    }

    /**
     * 判断2个date格式的日期是否超过指定天数
     */
    public static boolean isTimeOut(LocalDate beginTime, LocalDate endTime, int days) {
        return beginTime.until(endTime, ChronoUnit.DAYS) > days;
    }

    /**
     * @Author qs
     * @Date 2020/6/28
     * @Description 判断2个时间间隔是否超过指定分钟
     **/
    public static boolean isTimeOut(LocalDateTime beginTime, LocalDateTime endTime, int minute) {
        Duration duration = Duration.between(beginTime, endTime);
        return duration.toMinutes() > minute;
    }

    /**
     * @Author qs
     * @Date 2020/7/29
     * @Description 将小时和分钟格式的时间转成秒
     * @Param minuterStr 格式 mi:ss
     **/
    public static int minuteToInt(String minuterStr) {
        int seconds = 0;
        if (!Strings.isNullOrEmpty(minuterStr)) {
            String[] dateStr = minuterStr.split(":");
            int hours = Integer.parseInt(dateStr[0]) * 3600;
            int minutes = Integer.parseInt(dateStr[1]) * 60;
            seconds = hours + minutes;
        }
        return seconds;
    }

    /**
     * 根据传入的日期返回星期几
     *
     * @param day
     * @return java.lang.String
     * @author daxiong
     * @date 2020/8/26 10:17 上午
     */
    public static String getWeekDayStr(LocalDate day) {
        return WEEK_DAY_PREFIX + WEEK_ARRAY[day.getDayOfWeek().getValue()];
    }

    /**
     * 判断传入的日期是否为月初
     *
     * @param day
     * @return boolean
     * @author daxiong
     * @date 2020/8/27 2:27 下午
     */
    public static boolean isMonthHead(LocalDateTime day) {
        int dayOfMonth = day.getDayOfMonth();
        return dayOfMonth == 1;
    }

    /**
     * 判断传入的日期是否为年初
     *
     * @param day
     * @return boolean
     * @author daxiong
     * @date 2020/8/27 2:27 下午
     */
    public static boolean isYearHead(LocalDateTime day) {
        int dayOfYear = day.getDayOfYear();
        return dayOfYear == 1;
    }

    /**
     * 获取某天的最早时间，00：00
     *
     * @param date
     * @return java.time.LocalDateTime
     * @author daxiong
     * @date 2020/9/10 11:21 上午
     */
    public static LocalDateTime getEarliestTime(LocalDate date) {
        return LocalDateTime.of(date, LocalTime.MIN);
    }

    /**
     * 获取某天的最晚时间，23：59：999999
     *
     * @param date
     * @return java.time.LocalDateTime
     * @author daxiong
     * @date 2020/9/10 11:21 上午
     */
    public static LocalDateTime getLatestTime(LocalDate date) {
        // 不能用LocalTime.MAX，因为获取的时间是'23:59:59.999999999'，等价于往后一天
        return LocalDateTime.of(date, LocalTime.of(23, 59, 59));
    }


    /**
     * 获取GMT时间
     * eg: Wed, 02 Sep 2020 11:42:06 GMT
     *
     * @param date
     * @return java.lang.String
     * @author daxiong
     * @date 2020/9/2 11:42 上午
     */
    public static String formatGMT(TemporalAccessor date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH);
        return formatter.format(date);
    }
    //

    private static final ZoneOffset LOCAL_ZONE_OFF = ZoneOffset.systemDefault().getRules().getOffset(Instant.now());

    public static long getTimestamp() {

        return getTimestamp(LocalDateTime.now());
    }

    public static long getImestampMillion() {

        return getImestampMillion(LocalDateTime.now());
    }

    public static long getTimestamp(LocalDateTime localDateTime) {

        return localDateTime.toEpochSecond(LOCAL_ZONE_OFF);
    }

    public static long getTimestamp(LocalDateTime localDateTime, ZoneOffset offset) {

        return localDateTime.toEpochSecond(offset);
    }

    /**
     * 获取毫秒时间戳
     *
     * @param localDateTime
     * @return
     */
    public static long getImestampMillion(LocalDateTime localDateTime) {
        return localDateTime.toInstant(LOCAL_ZONE_OFF).toEpochMilli();
    }

    public static long getImestampMillion(LocalDateTime localDateTime, ZoneOffset offset) {
        return localDateTime.toInstant(offset).toEpochMilli();
    }

    public static LocalDateTime convertTimestampMillionToDateTime(Long time) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(time),
                ZoneId.systemDefault());
    }

    public static String secondToDateStr(Integer seconds) {
        if (seconds == null || seconds == 0) {
            return "00:00";
        }
        int hour = seconds / 3600;
        int minute = (seconds - hour * 3600) / 60;
        return Strings.padStart(String.valueOf(hour), 2, '0').concat(":").concat(
                Strings.padStart(String.valueOf(minute), 2, '0'));
    }

    /**
     * 将一天的时间按分钟分段，并返回传入时间的索引
     *
     * @param dateTime
     * @return java.lang.Integer
     * @author daxiong
     * @date 2020/12/9 上午10:10
     */
    public static Integer getSegmentIndexByInterval(LocalDateTime dateTime, Integer timeInterval) {
        if (Objects.equals(timeInterval, 0)) {
            return 0;
        }
        Integer minutes = date2MinuteTotal(dateTime);
        return minutes / timeInterval;
    }


    public static String getDurationTime(LocalDateTime beginTime, LocalDateTime endTime) {
        Duration duration = Duration.between(beginTime, endTime);
        //相差的天数
        long days = duration.toDays();
        //相差的小时数
        long hours = duration.toHours() - days * 24;
        long minutes = duration.toMinutes() - days * 24 * 60 - hours * 60;//相差的分钟数
        return days + "天" + hours + "小时" + minutes + "分钟";
    }

//    public static void main(String[] args) {
//        System.out.println(
//                getDurationTime(
//                        DateFormat.stringToDate("2021-06-20 00:01:02", DATETIME_FORMAT_STR), LocalDateTime.now()
//                )
//        );
//    }
}


